package de.ur.iw.wiki;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PageFormatter {

	private static final String REGEX_HEADER_START = "[^=]";
	private static final String REGEX_HEADER_MIDDLE = "=";
	private static final String REGEX_HEADER_END = "[^=]";
	private static final String TAG_LOWER_HEADER = "===";
	private static final String TAG_PARAGRAPH_START = "== ";
	private static final String TAG_PARAGRAPH_END = " ==";
	
	private static final int PARAGRAPHS_MAX_DEPTH = 6;

	private LinkCollector page;
	private String content;

	private LinkCollector currentParagraph = null;

	private WikiPage context;

	public PageFormatter(String content, LinkCollector linkCollection,
			WikiPage context) {
		this.page = linkCollection;
		this.content = content;
		this.context = context;
	}

	private void formatPage() {
		
		String[] paragraphs = {};
		
		for(int i=0; i<PARAGRAPHS_MAX_DEPTH; i++){
			paragraphs = content.split(getSplitRegex(i+2));
			if(paragraphs.length>1){
				break;
			}
		}

		if(paragraphs.length<2){
			return;
		}
		
		currentParagraph = page.getParagraphAt(0);

		// 1 index is the title,  2 content
		int start = 2;

		if (paragraphs.length % 2 == 0) {
			start = 1;
		} else if (currentParagraph != null) {
			// paragraph[0] is always the description
			computeLinksInText(paragraphs[0]);
		}

		// one index is the title, one the content (thus +2)
		for (int i = start; i < paragraphs.length; i += 2) {
			String name = paragraphs[i - 1].replaceAll("=", "");
			String text = paragraphs[i];
			currentParagraph = new Paragraph(name, context);
			if (text.contains(TAG_LOWER_HEADER)) {
				new PageFormatter(text, currentParagraph, context)
						.getFormattedPage();
			} else {
				computeLinksInText(text);
			}
			page.addParagraph(currentParagraph);
		}
	}

	private String getSplitRegex(int deep){
		String result = REGEX_HEADER_START;
		for(int i=0; i<deep; i++){
			result += REGEX_HEADER_MIDDLE;
		}
		result += REGEX_HEADER_END;
		return result;
	}
	
	private void computeLinksInText(String text) {
		Pattern pattern = Pattern.compile(WikiPage.LINK_REGEX);
		Matcher matcher = pattern.matcher(text);
		while (matcher.find()) {
			String rawName = matcher.group();
			String name = getName(rawName);
			if (name != null && !name.contains(context.getName() + "'#")) {
				if (name.contains("#")) {
					name = name.split("#")[0];
				}
				Link link = new Link(name);
				double pos = 1.0 * matcher.start() / text.length();
				double pPos = getParagraphPosition(currentParagraph.getName());
				link.getInfo().setInt(LinkInfo.KEY_POSITION_IN_PARAGRAPH,
						(int) (pos * 100));
				link.getInfo().setInt(LinkInfo.KEY_POSITION_OF_PARAGRAPH,
						(int) (pPos * 100));
				computeTypeOfLink(link);
			}
		}
	}

	private double getParagraphPosition(String pName) {
		pName = TAG_PARAGRAPH_START + pName + TAG_PARAGRAPH_END;
		String content = context.getContent();
		double result = 1.0 * content.indexOf(pName) / content.length();
		return result;
	}

	private void computeTypeOfLink(Link link) {
		LinkInfo info = link.getInfo();
		String name = link.getName();
		if (name.contains(WikiPage.CROSS_REFERENCE_SEPERATOR)) {
			String type = name.split(WikiPage.CROSS_REFERENCE_SEPERATOR)[0];
			info.setString(LinkInfo.KEY_TYPE, type);
		} else {
			info.setString(LinkInfo.KEY_TYPE, LinkInfo.VAL_LINK);
		}
		computeTypedLink(link);
	}

	private void computeTypedLink(Link link) {
		String type = link.getInfo().getString(LinkInfo.KEY_TYPE);

		if (type == null) {
			System.err.println("untyped link: " + link.getName());

		} else if (type.equals(LinkInfo.VAL_CATEGORY)) {
			context.addCategory(link);

		} else if (type.equals(LinkInfo.VAL_LINK)) {
			currentParagraph.add(link);

		} else if (type.equals(LinkInfo.VAL_FILE)) {
			context.addFile(link);
		}
	}

	private String getName(String rawName) {
		rawName = rawName.replaceAll("\\[", "");
		rawName = rawName.replaceAll("\\]", "");
		String[] names = rawName.split(WikiPage.LINK_SEPERATOR);
		if (names.length >= 1) {
			return names[0];
		} else {
			return null;
		}
	}

	public LinkCollector getFormattedPage() {
		formatPage();
		return page;
	}

}
